package org.ovirt.microvirt.services.situation.lom.impl;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.SocketException;

import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.ovirt.microvirt.beans.Host;
import org.ovirt.microvirt.beans.WalLomSettings;
import org.ovirt.microvirt.services.situation.lom.LightsOutService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.HostKey;
import com.jcraft.jsch.HostKeyRepository;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.UserInfo;

public class WalLomService implements LightsOutService {

	final static Logger logger = LoggerFactory.getLogger(WalLomService.class);

	public static byte[] mac(final String macStr) {
		try {
			return Hex.decodeHex(macStr.replaceAll(":", "").toCharArray());
		} catch (DecoderException e) {
			return null;
		}
	}

	public static String macStr(byte[] addr) {
		char[] encodeHex = Hex.encodeHex(addr);
		StringBuilder builder = new StringBuilder();
		for (int cntr = 0; cntr < encodeHex.length; cntr++) {
			builder.append(encodeHex[cntr]);
			if (cntr % 2 == 1 && cntr != encodeHex.length - 1) {
				builder.append(':');
			}
		}
		return builder.toString().toUpperCase();
	}

	@Override
	public void powerup(Host host) {
		try {
			final byte[] mac = mac(((WalLomSettings) host.getLomSettings())
					.getMac());
			final byte[] buff = new byte[102];
			for (int i = 0; i < 6; i++) {
				buff[i] = (byte) 0xff;
			}
			for (int i = 0; i < 16; i++) {
				System.arraycopy(mac, 0, buff, 6 + (6 * i), 6);
			}
			final InetAddress addr = InetAddress.getByName("228.5.6.7");
			final MulticastSocket multicastSocket = new MulticastSocket();
			multicastSocket.joinGroup(addr);
			final DatagramPacket packet = new DatagramPacket(buff, buff.length,
					addr, 9);
			multicastSocket.send(packet);
		} catch (SocketException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	@Override
	public void powerdown(Host host) {
		try {
			JSch sch = new JSch();
			sch.setHostKeyRepository(new HostKeyRepository() {

				public void remove(String host, String type, byte[] key) {
				}

				public void remove(String host, String type) {
				}

				public String getKnownHostsRepositoryID() {
					return null;
				}

				public HostKey[] getHostKey(String host, String type) {
					return null;
				}

				public HostKey[] getHostKey() {
					return null;
				}

				public int check(String host, byte[] key) {
					return HostKeyRepository.OK;
				}

				public void add(HostKey hostkey, UserInfo ui) {
				}
			});
			final Session session = sch.getSession("root", host.getAddr());
			session.setPassword(host.getRootPassword());
			session.connect();
			final Channel channel = session.openChannel("exec");
			((ChannelExec) channel).setCommand("poweroff");
			channel.connect();
			channel.disconnect();
			session.disconnect();
		} catch (JSchException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}
